home *** CD-ROM | disk | FTP | other *** search
/ Shareware Super Platinum 8 / Shareware Super Platinum 8.iso / mac / WIN_PRO / DS-1.ZIP;1 / PREPROC.ZIP / EVALUATE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-10  |  15.6 KB  |  559 lines

  1. /*
  2.  * This file contains functions to evaluate constant expressions for
  3.  *  conditional inclusion. These functions are organised as a recursive
  4.  *  decent parser based on the C grammar presented in the ANSI C Standard
  5.  *  document. The function eval() is called from the outside.
  6.  */
  7.  
  8. #include "../preproc/preproc.h"
  9.  
  10. /*
  11.  * Prototypes for static functions.
  12.  */
  13. hidden long primary        Params((struct token **tp, struct token *trigger));
  14. hidden long unary          Params((struct token **tp, struct token *trigger));
  15. hidden long multiplicative Params((struct token **tp, struct token *trigger));
  16. hidden long additive       Params((struct token **tp, struct token *trigger));
  17. hidden long shift          Params((struct token **tp, struct token *trigger));
  18. hidden long relation       Params((struct token **tp, struct token *trigger));
  19. hidden long equality       Params((struct token **tp, struct token *trigger));
  20. hidden long and            Params((struct token **tp, struct token *trigger));
  21. hidden long excl_or        Params((struct token **tp, struct token *trigger));
  22. hidden long incl_or        Params((struct token **tp, struct token *trigger));
  23. hidden long log_and        Params((struct token **tp, struct token *trigger));
  24. hidden long log_or         Params((struct token **tp, struct token *trigger));
  25.  
  26. #include "../preproc/pproto.h"
  27.  
  28. /*
  29.  * <primary> ::= <identifier>
  30.  *               defined <identifier>
  31.  *               defined '(' <identifier> ')'
  32.  *               <number>
  33.  *               <character-constant>
  34.  *               '(' <conditional> ')'
  35.  */
  36. static long primary(tp, trigger)
  37. struct token **tp;
  38. struct token *trigger;
  39.    {
  40.    struct token *t = NULL;
  41.    struct token *id = NULL;
  42.    long e1;
  43.    int i;
  44.    int is_hex_char;
  45.    char *s;
  46.  
  47.    switch ((*tp)->tok_id) {
  48.       case Identifier:
  49.          /*
  50.           * Check for "defined", it is the only reserved word in this expression
  51.           *  evaluation (See ANSI C Standard).
  52.           */
  53.          if (strcmp((*tp)->image, "defined") == 0) {
  54.             nxt_non_wh(&t);
  55.             if (t->tok_id == '(') {
  56.                nxt_non_wh(&id);
  57.                nxt_non_wh(&t);
  58.                if (t == NULL || t->tok_id != ')')
  59.                   errt1(id, "')' missing in 'defined' expression");
  60.                free_t(t);
  61.                }
  62.             else
  63.                id = t;
  64.             if (id->tok_id != Identifier)
  65.                errt1(id, "'defined' must be followed by an identifier");
  66.             advance_tok(tp);
  67.             if (m_lookup(id) == NULL)
  68.                e1 = 0L;
  69.             else
  70.                e1 = 1L;
  71.             free_t(id);
  72.             }
  73.          else {
  74.             advance_tok(tp);
  75.             e1 = 0L;   /* undefined: all macros have been expanded */
  76.             }
  77.          return e1;
  78.  
  79.       case PpNumber:
  80.          s = (*tp)->image;
  81.          e1 = 0L;
  82.          if (*s == '0') {
  83.             ++s;
  84.             if (*s == 'x' | *s == 'X') {
  85.                /*
  86.                 * Hex constant
  87.                 */
  88.                ++s;
  89.                if (*s == '\0' || *s == 'u' || *s == 'U' || *s == 'l' ||
  90.                     *s == 'L')
  91.                   errt2(*tp, "invalid hex constant in condition of #",
  92.                      trigger->image);
  93.                while (*s != '\0' && *s != 'u' && *s != 'U' && *s != 'l' &&
  94.                     *s != 'L') {
  95.                   e1 <<= 4;
  96.                   if (*s >= '0' && *s <= '9')
  97.                      e1 |= *s - '0';
  98.                   else
  99.                      switch (*s) {
  100.                         case 'a': case 'A': e1 |= 10; break;
  101.                         case 'b': case 'B': e1 |= 11; break;
  102.                         case 'c': case 'C': e1 |= 12; break;
  103.                         case 'd': case 'D': e1 |= 13; break;
  104.                         case 'e': case 'E': e1 |= 14; break;
  105.                         case 'f': case 'F': e1 |= 15; break;
  106.                         default:
  107.                            errt2(*tp, "invalid hex constant in condition of #",
  108.                               trigger->image);
  109.                         }
  110.                   ++s;
  111.                   }
  112.                }
  113.             else {
  114.                /*
  115.                 * Octal constant
  116.                 */
  117.                while (*s != '\0' && *s != 'u' && *s != 'U' && *s != 'l' &&
  118.                     *s != 'L') {
  119.                   if (*s >= '0' && *s <= '7')
  120.                      e1 = (e1 << 3) | (*s - '0');
  121.                   else
  122.                      errt2(*tp, "invalid octal constant in condition of #",
  123.                         trigger->image);
  124.                   ++s;
  125.                   }
  126.                }
  127.             }
  128.          else {
  129.             /*
  130.              * Decimal constant
  131.              */
  132.             while (*s != '\0' && *s != 'u' && *s != 'U' && *s != 'l' &&
  133.                  *s != 'L') {
  134.                if (*s >= '0' && *s <= '9')
  135.                   e1 = e1 * 10 + (*s - '0');
  136.                else
  137.                   errt2(*tp, "invalid decimal constant in condition of #",
  138.                      trigger->image);
  139.                ++s;
  140.                }
  141.             }
  142.             advance_tok(tp);
  143.             /*
  144.              * Check integer suffix for validity
  145.              */
  146.             if (*s == '\0')
  147.                return e1;
  148.             else if (*s == 'u' || *s == 'U') {
  149.                ++s;
  150.                if (*s == '\0')
  151.                   return e1;
  152.                else if ((*s == 'l' || *s == 'L') && *++s == '\0')
  153.                   return e1;
  154.                }
  155.             else if (*s == 'l' || *s == 'L') {
  156.                ++s;
  157.                if (*s == '\0')
  158.                   return e1;
  159.                else if ((*s == 'u' || *s == 'U') && *++s == '\0')
  160.                   return e1;
  161.                }
  162.             errt2(*tp, "invalid integer constant in condition of #",
  163.                trigger->image);
  164.  
  165.       case CharConst:
  166.       case LCharConst:
  167.          /*
  168.           * Wide characters are treated the same as characters. Only the
  169.           *  first byte of a multi-byte character is used.
  170.           */
  171.          s = (*tp)->image;
  172.          if (*s != '\\')
  173.             e1 = (long)*s;
  174.          else {
  175.             /*
  176.              * Escape sequence.
  177.              */
  178.             e1 = 0L;
  179.             ++s;
  180.             if (*s >= '0' && *s <= '7') {
  181.                 for (i = 1; i <= 3 && *s >= '0' && *s <= '7'; ++i, ++s)
  182.                    e1 = (e1 << 3) | (*s - '0');
  183.                 if (e1 != (long)(unsigned char)e1)
  184.                    errt1(*tp, "octal escape sequece larger than a character");
  185.                 e1 = (long)(char)e1;
  186.                 }
  187.             else switch (*s) {
  188.                case '\'': e1 = (long) '\''; break;
  189.                case '"':  e1 = (long) '"';  break;
  190.                case '?':  e1 = (long) '?';  break;
  191.                case '\\': e1 = (long) '\\'; break;
  192.                case 'a':  e1 = (long) Bell; break;
  193.                case 'b':  e1 = (long) '\b'; break;
  194.                case 'f':  e1 = (long) '\f'; break;
  195.                case 'n':  e1 = (long) '\n'; break;
  196.                case 'r':  e1 = (long) '\r'; break;
  197.                case 't':  e1 = (long) '\t'; break;
  198.                case 'v':  e1 = (long) '\v'; break;
  199.    
  200.                case 'x': 
  201.                   ++s;
  202.                   is_hex_char = 1;
  203.                   while (is_hex_char) {
  204.                      if (*s >= '0' && *s <= '9')
  205.                         e1 = (e1 << 4) | (*s - '0');
  206.                      else switch (*s) {
  207.                         case 'a': case 'A': e1 = (e1 << 4) | 10; break;
  208.                         case 'b': case 'B': e1 = (e1 << 4) | 11; break;
  209.                         case 'c': case 'C': e1 = (e1 << 4) | 12; break;
  210.                         case 'd': case 'D': e1 = (e1 << 4) | 13; break;
  211.                         case 'e': case 'E': e1 = (e1 << 4) | 14; break;
  212.                         case 'f': case 'F': e1 = (e1 << 4) | 15; break;
  213.                         default: is_hex_char = 0;
  214.                         }
  215.                      if (is_hex_char)
  216.                         ++s;
  217.                      if (e1 != (long)(unsigned char)e1)
  218.                         errt1(*tp,"hex escape sequece larger than a character");
  219.                      }
  220.                   e1 = (long)(char)e1;
  221.                   break;
  222.    
  223.                default:
  224.                   e1 = (long) *s;
  225.                }
  226.             }
  227.          advance_tok(tp);
  228.          return e1;
  229.  
  230.       case '(':
  231.          advance_tok(tp);
  232.          e1 = conditional(tp, trigger);
  233.          if ((*tp)->tok_id != ')')
  234.             errt2(*tp, "expecected ')' in conditional of #", trigger->image);
  235.          advance_tok(tp);
  236.          return e1;
  237.  
  238.       default:
  239.          errt2(*tp, "syntax error in condition of #", trigger->image);
  240.       }
  241.    }
  242.  
  243. /*
  244.  * <unary> ::= <primary> |
  245.  *             '+' <unary> |
  246.  *             '-' <unary> |
  247.  *             '~' <unary> |
  248.  *             '!' <unary>
  249.  */
  250. static long unary(tp, trigger)
  251. struct token **tp;
  252. struct token *trigger;
  253.    {
  254.    switch ((*tp)->tok_id) {
  255.       case '+':
  256.          advance_tok(tp);
  257.          return unary(tp, trigger);
  258.       case '-':
  259.          advance_tok(tp);
  260.          return -unary(tp, trigger);
  261.       case '~':
  262.          advance_tok(tp);
  263.          return ~unary(tp, trigger);
  264.       case '!':
  265.          advance_tok(tp);
  266.          return !unary(tp, trigger);
  267.       default:
  268.          return primary(tp, trigger);
  269.       }
  270.    }
  271.  
  272. /*
  273.  * <multiplicative> ::= <unary> |
  274.  *                      <multiplicative> '*' <unary> |
  275.  *                      <multiplicative> '/' <unary> |
  276.  *                      <multiplicative> '%' <unary>
  277.  */
  278. static long multiplicative(tp, trigger)
  279. struct token **tp;
  280. struct token *trigger;
  281.    {
  282.    long e1, e2;
  283.    int tok_id;
  284.  
  285.    e1 = unary(tp, trigger);
  286.    tok_id = (*tp)->tok_id;
  287.    while (tok_id == '*' || tok_id == '/' || tok_id == '%') {
  288.       advance_tok(tp);
  289.       e2 = unary(tp, trigger);
  290.       switch (tok_id) {
  291.          case '*':
  292.             e1 = (e1 * e2);
  293.             break;
  294.          case '/':
  295.             e1 = (e1 / e2);
  296.             break;
  297.          case '%':
  298.             e1 = (e1 % e2);
  299.             break;
  300.          }
  301.       tok_id = (*tp)->tok_id;
  302.       }
  303.    return e1;
  304.    }
  305.  
  306. /*
  307.  * <additive> ::= <multiplicative> |
  308.  *                <additive> '+' <multiplicative> |
  309.  *                <additive> '-' <multiplicative>
  310.  */
  311. static long additive(tp, trigger)
  312. struct token **tp;
  313. struct token *trigger;
  314.    {
  315.    long e1, e2;
  316.    int tok_id;
  317.  
  318.    e1 = multiplicative(tp, trigger);
  319.    tok_id = (*tp)->tok_id;
  320.    while (tok_id == '+' || tok_id == '-') {
  321.       advance_tok(tp);
  322.       e2 = multiplicative(tp, trigger);
  323.       if (tok_id == '+')
  324.          e1 = (e1 + e2);
  325.       else
  326.          e1 = (e1 - e2);
  327.       tok_id = (*tp)->tok_id;
  328.       }
  329.    return e1;
  330.    }
  331.  
  332. /*
  333.  * <shift> ::= <additive> |
  334.  *             <shift> '<<' <additive> |
  335.  *             <shift> '>>' <additive>
  336.  */
  337. static long shift(tp, trigger)
  338. struct token **tp;
  339. struct token *trigger;
  340.    {
  341.    long e1, e2;
  342.    int tok_id;
  343.  
  344.    e1 = additive(tp, trigger);
  345.    tok_id = (*tp)->tok_id;
  346.    while (tok_id == LShft || tok_id == RShft) {
  347.       advance_tok(tp);
  348.       e2 = additive(tp, trigger);
  349.       if (tok_id == LShft)
  350.          e1 = (e1 << e2);
  351.       else
  352.          e1 = (e1 >> e2);
  353.       tok_id = (*tp)->tok_id;
  354.       }
  355.    return e1;
  356.    }
  357.  
  358. /*
  359.  * <relation> ::= <shift> |
  360.  *                <relation> '<' <shift> |
  361.  *                <relation> '<=' <shift> |
  362.  *                <relation> '>' <shift> |
  363.  *                <relation> '>=' <shift>
  364.  */
  365. static long relation(tp, trigger)
  366. struct token **tp;
  367. struct token *trigger;
  368.    {
  369.    long e1, e2;
  370.    int tok_id;
  371.  
  372.    e1 = shift(tp, trigger);
  373.    tok_id = (*tp)->tok_id;
  374.    while (tok_id == '<' || tok_id == Leq || tok_id == '>' || tok_id == Geq) {
  375.       advance_tok(tp);
  376.       e2 = shift(tp, trigger);
  377.       switch (tok_id) {
  378.          case '<':
  379.             e1 = (e1 < e2);
  380.             break;
  381.          case Leq:
  382.             e1 = (e1 <= e2);
  383.             break;
  384.          case '>':
  385.             e1 = (e1 > e2);
  386.             break;
  387.          case Geq:
  388.             e1 = (e1 >= e2);
  389.             break;
  390.          }
  391.       tok_id = (*tp)->tok_id;
  392.       }
  393.    return e1;
  394.    }
  395.  
  396. /*
  397.  * <equality> ::= <relation> |
  398.  *                <equality> '==' <relation> |
  399.  *                <equality> '!=' <relation>
  400.  */
  401. static long equality(tp, trigger)
  402. struct token **tp;
  403. struct token *trigger;
  404.    {
  405.    long e1, e2;
  406.    int tok_id;
  407.  
  408.    e1 = relation(tp, trigger);
  409.    tok_id = (*tp)->tok_id;
  410.    while (tok_id == Equal || tok_id == Neq) {
  411.       advance_tok(tp);
  412.       e2 = relation(tp, trigger);
  413.       if (tok_id == Equal)
  414.          e1 = (e1 == e2);
  415.       else
  416.          e1 = (e1 != e2);
  417.       tok_id = (*tp)->tok_id;
  418.       }
  419.    return e1;
  420.    }
  421.  
  422. /*
  423.  * <and> ::= <equality> |
  424.  *           <and> '&' <equality>
  425.  */
  426. static long and(tp, trigger)
  427. struct token **tp;
  428. struct token *trigger;
  429.    {
  430.    long e1, e2;
  431.  
  432.    e1 = equality(tp, trigger);
  433.    while ((*tp)->tok_id == '&') {
  434.       advance_tok(tp);
  435.       e2 = equality(tp, trigger);
  436.       e1 = (e1 & e2);
  437.       }
  438.    return e1;
  439.    }
  440.  
  441. /*
  442.  * <excl_or> ::= <and> |
  443.  *               <excl_or> '^' <and>
  444.  */
  445. static long excl_or(tp, trigger)
  446. struct token **tp;
  447. struct token *trigger;
  448.    {
  449.    long e1, e2;
  450.  
  451.    e1 = and(tp, trigger);
  452.    while ((*tp)->tok_id == '^') {
  453.       advance_tok(tp);
  454.       e2 = and(tp, trigger);
  455.       e1 = (e1 ^ e2);
  456.       }
  457.    return e1;
  458.    }
  459.  
  460. /*
  461.  * <incl_or> ::= <excl_or> |
  462.  *               <incl_or> '|' <excl_or>
  463.  */
  464. static long incl_or(tp, trigger)
  465. struct token **tp;
  466. struct token *trigger;
  467.    {
  468.    long e1, e2;
  469.  
  470.    e1 = excl_or(tp, trigger);
  471.    while ((*tp)->tok_id == '|') {
  472.       advance_tok(tp);
  473.       e2 = excl_or(tp, trigger);
  474.       e1 = (e1 | e2);
  475.       }
  476.    return e1;
  477.    }
  478.  
  479. /*
  480.  * <log_and> ::= <incl_or> |
  481.  *               <log_and> '&&' <incl_or>
  482.  */
  483. static long log_and(tp, trigger)
  484. struct token **tp;
  485. struct token *trigger;
  486.    {
  487.    long e1, e2;
  488.  
  489.    e1 = incl_or(tp, trigger);
  490.    while ((*tp)->tok_id == And) {
  491.       advance_tok(tp);
  492.       e2 = incl_or(tp, trigger);
  493.       e1 = (e1 && e2);
  494.       }
  495.    return e1;
  496.    }
  497.  
  498. /*
  499.  * <log_or> ::= <log_and> |
  500.  *              <log_or> '||' <log_and>
  501.  */
  502. static long log_or(tp, trigger)
  503. struct token **tp;
  504. struct token *trigger;
  505.    {
  506.    long e1, e2;
  507.  
  508.    e1 = log_and(tp, trigger);
  509.    while ((*tp)->tok_id == Or) {
  510.       advance_tok(tp);
  511.       e2 = log_and(tp, trigger);
  512.       e1 = (e1 || e2);
  513.       }
  514.    return e1;
  515.    }
  516.  
  517. /*
  518.  * <conditional> ::= <log_or> |
  519.  *                   <log_or> '?' <conditional> ':' <conditional>
  520.  */
  521. long conditional(tp, trigger)
  522. struct token **tp;
  523. struct token *trigger;
  524.    {
  525.    long e1, e2, e3;
  526.  
  527.    e1 = log_or(tp, trigger);
  528.    if ((*tp)->tok_id == '?') {
  529.       advance_tok(tp);
  530.       e2 = conditional(tp, trigger);
  531.       if ((*tp)->tok_id != ':')
  532.          errt2(*tp, "expecected ':' in conditional of #", trigger->image);
  533.       advance_tok(tp);
  534.       e3 = conditional(tp, trigger);
  535.       return e1 ? e2 : e3;
  536.       }
  537.    else
  538.       return e1;
  539.    }
  540.  
  541. /*
  542.  * eval - get the tokens for a conditional and evaluate it to 0 or 1.
  543.  *  trigger is the preprocessing directive that triggered the evaluation;
  544.  *  it is used for error messages.
  545.  */
  546. int eval(trigger)
  547. struct token *trigger;
  548.    {
  549.    struct token *t = NULL;
  550.    int result;
  551.  
  552.    advance_tok(&t);
  553.    result = (conditional(&t, trigger) != 0L);
  554.    if (t->tok_id != PpDirEnd)
  555.       errt2(t, "expected end of condition of #", trigger->image);
  556.    free_t(t);
  557.    return result;
  558.    }
  559.